// AutoEnumString.cpp: implementation of the CAutoEnumString class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "AutoEnumString.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CAutoEnumString::CAutoEnumString()
{
	m_Ref = 0;
	m_iterCur = 0;
}

CAutoEnumString::~CAutoEnumString()
{

}

int CAutoEnumString::AddString(LPCSTR lpszStr)
{
	return m_arString.Add(lpszStr);
}

ULONG CAutoEnumString::AddRef()
{
	m_Ref ++;
	return  (ULONG) m_Ref;
}

ULONG CAutoEnumString::Release()
{
	m_Ref --;
	if (m_Ref == 0 ) {
		delete this;
		return 0;
	}
	return  (ULONG) m_Ref;
}

HRESULT CAutoEnumString::QueryInterface(const IID &iid, void **ppv)
{
	if ( iid == IID_IUnknown )
	{
		*ppv = (IEnumString *) this ;
				((IEnumString *)(*ppv))->AddRef() ;
	} else if ( iid == IID_IEnumString ) 
	{
		*ppv = (IEnumString *) this ;
				((IEnumString *)(*ppv))->AddRef() ;
	}
	else
	{
		*ppv = NULL;
		return E_NOINTERFACE ;
	}
	return S_OK;
}

HRESULT CAutoEnumString::Next(ULONG celt, LPOLESTR *rgelt, ULONG *pceltFetched)
{
	if (rgelt == NULL || (celt != 1 && pceltFetched == NULL)) 
        return E_POINTER; 
    if (m_iterCur == m_arString.GetSize()) 
        return E_FAIL; 
    ULONG nRem = (ULONG)(m_arString.GetSize() - m_iterCur); 
    HRESULT hRes = S_OK; 
    if (nRem < celt) 
        hRes = S_FALSE; 
    ULONG nMin = min(celt, nRem); 
    if (pceltFetched != NULL) 
        *pceltFetched = nMin; 
    while(nMin--) {
		CString str = m_arString.GetAt(m_iterCur++);
		BSTR bstr = str.AllocSysString();
        Copy(rgelt++, &bstr); 
	}
    return hRes; 
}

HRESULT CAutoEnumString::Copy(LPOLESTR* p1, LPOLESTR* p2)
{
	HRESULT hr = S_OK;
	(*p1) = (LPOLESTR)CoTaskMemAlloc(sizeof(OLECHAR)*(ocslen(*p2)+1));
	if (*p1 == NULL)
		hr = E_OUTOFMEMORY;
	else
		ocscpy(*p1,*p2);
	return hr;
}

HRESULT CAutoEnumString::Reset(void)
{
	m_iterCur = 0;
	return S_OK;
}

HRESULT CAutoEnumString::Skip(ULONG celt)
{
	if (m_arString.GetSize() - m_iterCur <  (long)celt)
	{
		m_iterCur = m_arString.GetSize();
		return S_FALSE;
	}
	m_iterCur += celt;
	return S_FALSE;
}

HRESULT CAutoEnumString::Clone(IEnumString** ppEnum)
{
	HRESULT hRes = E_POINTER;
	if (ppEnum != NULL)
	{
		CAutoEnumString* p = NULL;
		p = new CAutoEnumString;
		if (p == NULL)
		{
			*ppEnum = NULL;
			hRes = E_OUTOFMEMORY;
		}
		else
		{
			for(int i=0;i<m_arString.GetSize();i++)
				p->AddString(m_arString.GetAt(i));
			hRes = p->QueryInterface(IID_IEnumString, (void**)ppEnum);
			if (FAILED(hRes))
				delete p;
		}
	}
	return hRes;
}
